package com.chen.common.scheduler.config;

import com.chen.common.scheduler.aop.JobAop;
import com.chen.common.scheduler.controller.JobController;
import com.chen.common.scheduler.inter.DefaultJobTaskConfigs;
import com.chen.common.scheduler.inter.JobTaskConfigInter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author ChenJinLong
 * @since 2023/10/27
 */
@Slf4j
@Configuration
@EnableScheduling
@ConditionalOnProperty(value = "enable.scheduler-job", matchIfMissing = true, havingValue = "true")
public class SchedulerJobConfig {

	@Value("${scheduler.pool-size:500}")
	private Integer poolSize;
	@Value("${scheduler.await-seconds:30}")
	private Integer awaitSeconds;
	@Value("${scheduler.await-on-shutdown:false}")
	private Boolean awaitOnShutdown;
	@Value("${scheduler.thread-name-prefix:job-thread-}")
	private String threadNamePrefix;

	@Bean
	@ConditionalOnMissingBean(JobTaskConfigInter.class)
	public DefaultJobTaskConfigs defaultJobTaskConfigs(){
		return new DefaultJobTaskConfigs();
	}

	@Bean
	public JobTaskConfig dispatchCenter(){
		return new JobTaskConfig();
	}

	@Bean
	public JobAop jobAop(){
		return new JobAop();
	}

	@Bean
	public JobController jobController(){
		return new JobController();
	}

	@Bean
	@Primary
	public ThreadPoolTaskScheduler threadPoolTaskScheduler() { 
		ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
		scheduler.setPoolSize(poolSize);
		scheduler.setThreadNamePrefix(threadNamePrefix);
		scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		// 等待的时间，超过这个时间就强制销毁，因为不能无限的等待下去以确保应用最后能够被关闭
		scheduler.setAwaitTerminationSeconds(awaitSeconds);
		// 调度器shutdown被调用时, 是否等待当前被调度的任务完成
		scheduler.setWaitForTasksToCompleteOnShutdown(awaitOnShutdown);
		scheduler.setErrorHandler(throwable -> log.error("", throwable));

		scheduler.initialize();
		return scheduler;
	}
}
